package hhm.android.library.calendar.view

import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import hhm.android.library.calendar.DateUtil
import hhm.android.library.calendar.bean.*
import hhm.android.library.calendar.util.dip2px
import java.text.SimpleDateFormat
import java.util.*

/**
 *
 */
class CalendarView : LinearLayout {
    private var startWithSunday = true
    private val rvDate = RecyclerView(context)
    private val adapter = DateAdapter()
    private val mList = mutableListOf<DateBean>()

    private val calendar = Calendar.getInstance()
    private val currentYear = calendar.get(Calendar.YEAR)
    private val currentMonth = calendar.get(Calendar.MONTH) + 1
    private val currentDate = calendar.get(Calendar.DATE)
    private val todayYear = calendar.get(Calendar.YEAR)
    private val todayMonth = calendar.get(Calendar.MONTH) + 1
    private val todayDate = calendar.get(Calendar.DATE)

    private lateinit var list: ArrayList<Long>

    constructor(context: Context) : super(context)

    constructor(
        context: Context,
        attrs: AttributeSet
    ) : super(context, attrs)

    constructor(
        context: Context,
        attrs: AttributeSet,
        defStyle: Int
    ) : super(
        context,
        attrs,
        defStyle
    )

    private fun addWeekView() {
        val week = LinearLayout(context).apply {
            setBackgroundColor(Color.parseColor("#00FFFFFF"))
            val headParams = LayoutParams(LayoutParams.MATCH_PARENT, dip2px(context, 48f))
            layoutParams = headParams
            orientation = HORIZONTAL
            setPadding(dip2px(context, 15f), 0, dip2px(context, 15f), 0)
        }
        val weekDay = if (startWithSunday) listOf("日", "一", "二", "三", "四", "五", "六") else
            listOf("一", "二", "三", "四", "五", "六", "日")
        val itemParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT).apply {
            weight = 1.5f
        }
        for (i in weekDay) {
            val tv = TextView(context).apply {
                layoutParams = itemParams
                gravity = Gravity.CENTER
                setTextColor(Color.parseColor("#999999"))
                setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
                text = i
            }
            week.addView(tv)
        }
        addView(week)
    }

    private fun initDate(menthDiff: Int, startYear: Int, startMonth: Int, startDay: Int) {
        val monthList = mutableListOf<MonthBean>()

        val calendar = Calendar.getInstance()
        // 控制月份本月之前显示几个月
        calendar.set(startYear, startMonth, startDay)
        for (i in 0 until menthDiff) {
            val year = calendar.get(Calendar.YEAR)
            val month = calendar.get(Calendar.MONTH) + 1
            val bean = MonthBean(year, month)
            monthList.add(bean)
            calendar.add(Calendar.MONTH, 1)
        }

        for (bean in monthList) {
            val dateList = mutableListOf<DateBean>()
            // 这个月的第一天
            calendar.set(bean.year, bean.month - 1, 1)
            val currentYear = calendar.get(Calendar.YEAR)
            val currentMonth = calendar.get(Calendar.MONTH)
            val dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)
            // 第一天之前空几天 起始的天数不同的话，
            var firstOffset = if (startWithSunday) dayOfWeek - 1 else dayOfWeek - 2
            //当月最后一天
            calendar.add(Calendar.MONTH, 1)
            calendar.add(Calendar.DATE, -1)

            //每个月份日期循环结束
            val dayOfSum: Int
            var lastOffset: Int
            if (bean.year == todayYear && bean.month == todayMonth) {
                dayOfSum = todayDate
                calendar.set(todayYear, todayMonth, todayDate)
                val lastMonthLastDay = calendar.get(Calendar.DAY_OF_WEEK)
                lastOffset = 7 - lastMonthLastDay
            } else {
                dayOfSum = calendar.get(Calendar.DATE)
                val lastDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)
                lastOffset = 7 - lastDayOfWeek
            }
            //每个月份日期循环开始
            val startDayOfSum: Int
            if (bean.year == startYear && bean.month == startMonth + 1) {
                startDayOfSum = startDay
                calendar.set(startYear, startMonth, startDay)
                val firstMonthFirstDay = calendar.get(Calendar.DAY_OF_WEEK)
                firstOffset =
                    if (startWithSunday) firstMonthFirstDay - 1 else firstMonthFirstDay - 2
            } else {
                startDayOfSum = 1
            }

            // 这个月起始的空占位符
            for (i in 0 until firstOffset) {
                val dateBean = DateBean(
                    year = currentYear,
                    month = currentMonth + 1,
                    day = 0,
                    type = TYPE_DATE_BLANK,
                    hasData = false
                )
                dateList.add(dateBean)
            }
            // 这个月的所有日期
            for (i in startDayOfSum..dayOfSum) {
                val sdf = SimpleDateFormat("yyyy/MM/dd")
                val format = sdf.parse("" + currentYear + "/" + (currentMonth + 1) + "/" + i)
                var b = false
                for (j in 0 until list.size) {
                    if (format.time == list[j]) {
                        b = true
                    }
                }
                val dateBean = DateBean(
                    year = currentYear,
                    month = currentMonth + 1,
                    day = i,
                    type = TYPE_DATE_NORMAL,
                    hasData = b,
                    isChooseDay = format.time == list[0]
                )
                checkIsToday(dateBean)
                dateList.add(dateBean)
            }
            // 这个月结束的空白占位符
            for (i in 0 until lastOffset) {
                val dateBean = DateBean(
                    year = currentYear,
                    month = currentMonth + 1,
                    day = 0,
                    type = TYPE_DATE_BLANK,
                    hasData = false
                )
                dateList.add(dateBean)
            }
            bean.dateList = dateList
        }
        // 添加头部月份title，同时完成整个月份Adapter内List的构造
        for (bean in monthList) {
            val titleBean = DateBean(
                year = bean.year,
                month = bean.month,
                day = 0,
                type = TYPE_DATE_TITLE,
                hasData = true
            )
            mList.add(titleBean)
            mList.addAll(bean.dateList)
        }
    }

    private fun addCalendarView() {
        val rvParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
        val gridLayoutManager = GridLayoutManager(context, 7)
        this.adapter.setNewList(mList)
        rvDate.apply {
            adapter = this@CalendarView.adapter
            layoutParams = rvParams
            layoutManager = gridLayoutManager
            //此处是一个动画，可以把当前年月日固定在顶部
//            addItemDecoration(CalendarDecoration(context) { position ->
//                //返回年月栏数据，如2019年1月
//                if (position < mList.size) {
//                    mList[position].groupName
//                } else {
//                    ""
//                }
//            })
            setPadding(dip2px(context, 15f), 0, dip2px(context, 15f), 0)
            clipChildren = false
            clipToPadding = false

            gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
                override fun getSpanSize(i: Int): Int {
                    //设置每行item个数，若是title则占7个位置，若是空白或日期则占一个位置
                    return if (mList[i].type == TYPE_DATE_TITLE) 7 else 1
                }
            }
        }
        addView(rvDate)
        val todayPos = mList.indexOfFirst { it.isToday }
        if (todayPos != -1) rvDate.scrollToPosition(todayPos) else
            rvDate.scrollToPosition(mList.size - 1)
    }

    private fun checkIsToday(bean: DateBean) {
//        if (bean.year == currentYear && bean.month == currentMonth && bean.day == currentDate) {
//            bean.isToday = true
//            bean.isChooseDay = true
//        }
    }

    fun setDateClick(listener: ((DateBean, View, Int) -> Unit)?) {
        adapter.setOnItemClickListener(listener)
    }


    fun updateSelectDay(bean: DateBean) {
        val beforeBean = mList.find { it.isChooseDay }
        val beforePosition = mList.indexOfFirst { it.isChooseDay }
        if (bean == beforeBean) return
        beforeBean?.run { isChooseDay = false }
        bean.isChooseDay = true
        val selectPos = mList.indexOf(bean)
        if (beforePosition != -1) adapter.notifyItemChanged(beforePosition)
        if (selectPos != -1) adapter.notifyItemChanged(selectPos)
    }

    fun init(list: ArrayList<Long>) {
        init(list, isShowWeek = true, startWithSunday = true)
    }

    fun init(list: ArrayList<Long>, isShowWeek: Boolean, startWithSunday: Boolean) {
        this.list = list

        val lastDate = list[list.size - 1]
        val sdf = SimpleDateFormat("yyyy/MM/dd")
        val format = sdf.format(lastDate)
        val split = format.split("/")
        val startYear = split[0].toInt()
        val startMonth = split[1].toInt() - 1
        val startDay = split[2].toInt()
        val menthDiff = DateUtil.getMonthDiff(Date(lastDate), Date()) + 1

        this.startWithSunday = startWithSunday
        orientation = VERTICAL
        if (isShowWeek) {
            addWeekView()
        }
        initDate(menthDiff, startYear, startMonth, startDay)
        addCalendarView()
    }
}